 
 <template>
  <div class="text-ellipsis">
    <div class="text" :style="{height}">
      <div v-if="isVisible" class="btn" @click="toggle">
        <span class="btn-text">{{isExpand ? '收起' : '展开'}}</span>
      </div>
      <div ref="textRef" :style="commonStyle">
        <slot />
      </div>
    </div>
  </div>
</template>
 
<script>
export default {
  name: "TextEllipsis",
  props: {
    fontSize: {
      type: Number,
      default: 14
    },
    lines: {
      type: Number,
      default: 1
    },
    lineHeight: {
      type: Number,
      default: 20
    }
  },
  data () {
    return {
      isExpand: false,
      isVisible: false,
      textHeight: 0
    }
  },
  computed: {
    height () {
      if (this.isExpand) {
        return this.$refs.textRef.clientHeight + 'px';
      } else {
        return Math.min((this.lines * this.lineHeight), this.textHeight) + 'px';
      }
    },
    commonStyle () {
      return {
        lineHeight: this.lineHeight + 'px',
        fontSize: this.fontSize + 'px',
      }
    }
  },
  mounted () {
    this.init();
    // 监听插槽变化
    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation.type === "characterData") {
          this.init();
        }
      });
    });
    observer.observe(this.$refs.textRef, {
      characterData: true,
      subtree: true,
      childList: true
    });
  },
  methods: {
    init () {
      this.isExpand = false;
      this.textHeight = this.$refs?.textRef?.clientHeight || 0;
      this.isVisible = this.textHeight > this.lines * this.lineHeight;
    },
    toggle () {
      this.isExpand = !this.isExpand;
    }
  }
}
</script>
 
<style lang="scss" scoped>
.text-ellipsis {
  display: flex;
  overflow: hidden;
  -webkit-text-size-adjust: none;
}
.text {
  font-size: 20px;
  transition: 0.3s height;
}
.text::before {
  content: "";
  height: calc(100% - 20px);
  float: right;
}
.btn {
  float: right;
  clear: both;
  font-size: 14px;
  line-height: 20px;

  .ellipsis {
    color: #fff;
  }
  .reverse {
    transform: rotateX(180deg);
    transition: 0.3s;
  }
  .btn-text {
    color: #409eff;
    cursor: pointer;
    margin-left: 4px;
    font-size: 14px;
    line-height: 20px;
  }
}
</style>